package com.lcf.framework.utils.oss.ali;

import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.lcf.framework.utils.FileUtils;
import com.lcf.framework.utils.ImageUtils;
import com.lcf.framework.config.oss.AliOssConfig;
import com.lcf.framework.utils.oss.IOssUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * 阿里oss
 *
 * @author lcf
 */
@Component
public class AliOssUtils implements IOssUtils {
    @Resource
    private AliOssConfig aliOssConfig;

    /**
     * 上传图片
     *
     * @param file       文件
     * @param path       相对路径
     * @param isCompress 是否压缩
     */
     @Override
     public String uploadImg(String path, MultipartFile file, boolean isCompress) {
        if (file == null) {
            return "";
        }

        // 随机文件名
        String fileName = FileUtils.getRandomFileName(file.getOriginalFilename());
        try {
            InputStream inputStream = isCompress ? ImageUtils.compressImg(file) : file.getInputStream();
            return uploadFile(path, fileName, inputStream);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 上传图片
     *
     * @param path       相对路径
     * @param isCompress 是否压缩
     */
    @Override
    public String uploadImg(String path, InputStream inputStream, boolean isCompress) {
        // 随机文件名
        String fileName = IdUtil.getSnowflake().nextIdStr() + ".jpg";
        try {
            InputStream stream = isCompress ? ImageUtils.compressImg(inputStream) : inputStream;
            return uploadFile(path, fileName, stream);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 上传图片
     *
     * @param url        文件url
     * @param path       相对路径
     * @param isCompress 是否压缩
     */
    @Override
    public String uploadImg(String path, String url, boolean isCompress) {
        if (StringUtils.isBlank(url)) {
            return "";
        }

        // 随机文件名
        String fileName = FileUtils.getRandomFileName(url);
        try {
            InputStream inputStream = isCompress ? ImageUtils.compressImg(new URL(url).openStream()) : new URL(url).openStream();
            return uploadFile(path, fileName, inputStream);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 更新图片
     *
     * @param inputStream 图片流
     * @param oldName     旧图片名
     */
    @Override
    public String updateImg(String bucket, InputStream inputStream, String oldName, boolean isCompress) {
        delFile(bucket + "/" + oldName);
        return uploadImg(bucket, inputStream, isCompress);
    }

    /**
     * 更新图片
     *
     * @param file    图片
     * @param oldName 旧图片名
     */
    @Override
    public String updateImg(String bucket, MultipartFile file, String oldName, boolean isCompress) {
        delFile(bucket + "/" + oldName);
        return uploadImg(bucket, file, isCompress);
    }

    /**
     * 更新图片
     *
     * @param fileUrl 新图片路径
     * @param oldName 旧图片名
     */
    @Override
    public String updateImg(String bucket, String fileUrl, String oldName, boolean isCompress) {
        delFile(bucket + "/" + oldName);
        return uploadImg(bucket, fileUrl, isCompress);
    }

    /**
     * 上传文件
     *
     * @param file 文件
     * @param path 相对路径
     */
    @Override
    public String uploadFile(String path, MultipartFile file) {
        if (file == null) {
            return "";
        }

        // 随机文件名
        String fileName = FileUtils.getRandomFileName(file.getOriginalFilename());
        try {
            return uploadFile(path, fileName, file.getInputStream());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 上传文件
     *
     * @param url  文件url
     * @param path 相对路径
     */
    @Override
    public String uploadFile(String path, String url) {
        if (StringUtils.isBlank(url)) {
            return "";
        }

        // 随机文件名
        String fileName = FileUtils.getRandomFileName(url);
        try {
            return uploadFile(path, fileName, new URL(url).openStream());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 更新文件
     *
     * @param inputStream 文件流
     * @param oldName     旧文件名
     */
    @Override
    public String updateFile(String bucket, InputStream inputStream, String oldName) {
        delFile(bucket + "/" + oldName);
        return uploadFile(bucket, oldName, inputStream);
    }

    /**
     * 更新文件
     *
     * @param file    文件
     * @param oldName 旧文件名
     */
    @Override
    public String updateFile(String bucket, MultipartFile file, String oldName) {
        delFile(bucket + "/" + oldName);
        return uploadFile(bucket, file);
    }

    /**
     * 更新文件
     *
     * @param fileUrl 新文件路径
     * @param oldName 旧文件名
     */
    @Override
    public String updateFile(String bucket, String fileUrl, String oldName) {
        delFile(bucket + "/" + oldName);
        return uploadFile(bucket, fileUrl);
    }

    @Override
    public void delFile(String bucket, String fileUrl) {
        delFile(bucket + "/" + fileUrl);
    }

    /**
     * 获取文件绝对路径
     */
    @Override
    public String getAbsoluteUrl(String fileName) {
        if (StringUtils.isBlank(fileName)) {
            return "";
        }
        return "https://" + aliOssConfig.getDomain() + "/" + fileName;
    }

    /**
     * 获取文件相对路径
     */
    @Override
    public String getRelativeUrl(String url) {
        if (StringUtils.isBlank(url)) {
            return "";
        }

        return url.replace("https://" + aliOssConfig.getDomain() + "/", "");
    }

    @Override
    public Long getFileSize(String fileName) {
        return null;
    }

    /**
     * 获取client
     */
    private OSS getClient() {
        String endPoint = aliOssConfig.getEndPoint();
        String accessKeyId = aliOssConfig.getAccessKeyId();
        String accessKeySecret = aliOssConfig.getAccessKeySecret();
        // 创建OSSClient实例。
        return new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
    }

    /**
     * 上传
     *
     * @param fileName    文件名称
     * @param inputStream 文件流
     * @param path        相对路径
     */
    private String uploadFile(String path, String fileName, InputStream inputStream) {
        OSS ossClient = getClient();
        ObjectMetadata meta = new ObjectMetadata();
        // 设置内容被下载时的编码格式。
        meta.setContentEncoding("utf-8");
        meta.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));

        ossClient.putObject(aliOssConfig.getBucketName(), path + "/" + fileName, inputStream);
        // 关闭OSSClient。
        ossClient.shutdown();

        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return path + "/" + fileName;
    }

    /**
     * 删除文件
     */
    private void delFile(String fileName) {
        OSS ossClient = getClient();
        // 删除文件。如需删除文件夹，请将ObjectName设置为对应的文件夹名称。如果文件夹非空，则需要将文件夹下的所有object删除后才能删除该文件夹。
        ossClient.deleteObject(aliOssConfig.getBucketName(), fileName);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 获取文件扩展名
     *
     * @param fileName 文件名称
     */
    private static String getFileSuffix(String fileName) {
        //获取文件的后缀名 .xxx
        return fileName.substring(fileName.lastIndexOf("."));
    }

    private static String getContentType(String filesufix) {
        if (filesufix.equalsIgnoreCase(".bmp")) {
            return "image/bmp";
        }
        if (filesufix.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (filesufix.equalsIgnoreCase(".jpeg") ||
                filesufix.equalsIgnoreCase(".jpg") ||
                filesufix.equalsIgnoreCase(".png")) {
            return "image/jpg";
        }
        if (filesufix.equalsIgnoreCase(".html")) {
            return "text/html";
        }
        if (filesufix.equalsIgnoreCase(".txt")) {
            return "text/plain";
        }
        if (filesufix.equalsIgnoreCase(".vsd")) {
            return "application/vnd.visio";
        }
        if (filesufix.equalsIgnoreCase(".pptx") ||
                filesufix.equalsIgnoreCase(".ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (filesufix.equalsIgnoreCase(".docx") ||
                filesufix.equalsIgnoreCase(".doc")) {
            return "application/msword";
        }
        if (filesufix.equalsIgnoreCase(".xml")) {
            return "text/xml";
        }
        return "image/jpg";
    }
}
